package com.effectiv.gooruda.rest.service.api;


import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import lombok.Getter;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;

import com.effectiv.gooruda.rest.docs.annotation.Api;
import com.effectiv.gooruda.rest.docs.annotation.ApiHeader;
import com.effectiv.gooruda.rest.docs.annotation.ApiHeaders;
import com.effectiv.gooruda.rest.docs.annotation.ApiMethod;
import com.effectiv.gooruda.rest.docs.annotation.ApiParam;
import com.effectiv.gooruda.rest.docs.annotation.ApiResponseObject;
import com.effectiv.gooruda.rest.docs.pojo.ApiVerb;
import com.effectiv.gooruda.rest.domain.Session;
import com.effectiv.gooruda.rest.domain.User;
import com.effectiv.gooruda.rest.ext.SecurityContextHolder;

@Path("/session")
@Api(name = "Session API", description = "Session management API.")
public abstract class SessionService {
	
	private final String COLLECTION_BASE = "c_app_session_";
	
	@Getter
	@Autowired
	private MongoTemplate template;
	
	protected String getCollection(){
		return COLLECTION_BASE + SecurityContextHolder.get().getId();
	}
	
	/**
	 * Get all attributes for a session.
	 * @param sessionId
	 * @return
	 */
	
	@ApiMethod(path = "/api/session/getattributes/{sessionId}", verb = ApiVerb.GET, description = "Get all session attributes.", 
			produces = { MediaType.APPLICATION_JSON }, consumes = { MediaType.APPLICATION_JSON })
	@ApiHeaders(headers = {
			@ApiHeader(name = "signature", description = "Authentication signature."),
			@ApiHeader(name = "public-key", description = "Public key of the application.") })
	@Path("/getattributes/{sessionId}")
	@GET	
	@Produces(MediaType.APPLICATION_JSON)
	public abstract @ApiResponseObject Response getAttributes(
			@PathParam("sessionId") @ApiParam(name="sessionId", description="Session Id") String sessionId);
	
	/**
	 * Get a request attribute value for a given key.
	 * @param sessionId
	 * @param key
	 * @return
	 */
	
	@ApiMethod(path = "/api/session/getattribute/{sessionId}/{key}", verb = ApiVerb.GET, description = "Get a request attribute value for a given key.", 
			produces = { MediaType.APPLICATION_JSON }, consumes = { MediaType.APPLICATION_JSON })
	@ApiHeaders(headers = {
			@ApiHeader(name = "signature", description = "Authentication signature."),
			@ApiHeader(name = "public-key", description = "Public key of the application.") })
	@Path("/getattribute/{sessionId}/{key}")
	@GET	
	@Produces(MediaType.APPLICATION_JSON)
	public abstract @ApiResponseObject Response getAttribute(
			@PathParam("sessionId") @ApiParam(name="sessionId", description="Session Id") String sessionId, 
			@PathParam("key") @ApiParam(name="key", description="Attribute key") String key);
	
	/**
	 * Find session by user name
	 * @param userName
	 * @return
	 */
	@ApiMethod(path = "/api/session/findsessionbyuser/{userName}", verb = ApiVerb.GET, description = "Find session by user name.", 
			produces = { MediaType.APPLICATION_JSON }, consumes = { MediaType.APPLICATION_JSON })
	@ApiHeaders(headers = {
			@ApiHeader(name = "signature", description = "Authentication signature."),
			@ApiHeader(name = "public-key", description = "Public key of the application.") })
	@Path("/findsessionbyuser/{userName}")
	@GET	
	@Produces(MediaType.APPLICATION_JSON)
	public abstract @ApiResponseObject Response findSessionByUser(
			@PathParam("userName") @ApiParam(name="userName", description="User Name") String userName);
	
	/**
	 * Create a new session for an user.
	 * @param userName
	 * @return
	 */
	
	@ApiMethod(path = "/api/session/{userName}", verb = ApiVerb.POST, description = "Create a new session for an user.", 
			produces = { MediaType.APPLICATION_JSON }, consumes = { MediaType.APPLICATION_JSON })
	@ApiHeaders(headers = {
			@ApiHeader(name = "signature", description = "Authentication signature."),
			@ApiHeader(name = "public-key", description = "Public key of the application.") })
	@Path("/{userName}")
	@POST	
	@Produces(MediaType.APPLICATION_JSON)
	public abstract @ApiResponseObject Response create(@PathParam("userName") @ApiParam(name="userName", description="User Name") String userName);
	
	
	
	/**
	 * Invalidates an user session
	 * @param sessionId
	 */
	
	@ApiMethod(path = "/api/session/invalidate/{sessionId}", verb = ApiVerb.POST, description = "Create a new session for an user.", 
			produces = { MediaType.APPLICATION_JSON }, consumes = { MediaType.APPLICATION_JSON })
	@ApiHeaders(headers = {
			@ApiHeader(name = "signature", description = "Authentication signature."),
			@ApiHeader(name = "public-key", description = "Public key of the application.") })
	@Path("/invalidate/{sessionId}")
	@POST	
	@Produces(MediaType.APPLICATION_JSON)
	
	public abstract @ApiResponseObject Response invalidate(
			@PathParam("sessionId") @ApiParam(name="sessionId", description="Session Id") String sessionId);
	
	/**
	 * Removes all session attributes.
	 * @param sessionId
	 * @return
	 */
	
	@ApiMethod(path = "/api/session/removeallattributes/{sessionId}", verb = ApiVerb.DELETE, description = "Removes all session attributes.", 
			produces = { MediaType.APPLICATION_JSON }, consumes = { MediaType.APPLICATION_JSON })
	@ApiHeaders(headers = {
			@ApiHeader(name = "signature", description = "Authentication signature."),
			@ApiHeader(name = "public-key", description = "Public key of the application.") })
	@Path("/removeallattributes/{sessionId}")
	@DELETE	
	@Produces(MediaType.APPLICATION_JSON)
	
	public abstract @ApiResponseObject Response removeAllAttributes(
			@PathParam("sessionId") @ApiParam(name="sessionId", description="Session Id")  String sessionId);
	
	/**
	 * Remove a session attribute by key.
	 * @param sessionId
	 * @param key
	 * @return
	 */
	
	@ApiMethod(path = "/api/session/removeattribute/{sessionId}/{key}", verb = ApiVerb.DELETE, description = "Remove a session attribute by key.", 
			produces = { MediaType.APPLICATION_JSON }, consumes = { MediaType.APPLICATION_JSON })
	@ApiHeaders(headers = {
			@ApiHeader(name = "signature", description = "Authentication signature."),
			@ApiHeader(name = "public-key", description = "Public key of the application.") })
	@Path("/removeattribute/{sessionId}/{key}")
	@DELETE	
	@Produces(MediaType.APPLICATION_JSON)
	
	public abstract @ApiResponseObject Response removeAttribute(
			@PathParam("sessionId") @ApiParam(name="sessionId", description="Session Id") String sessionId, 
			@PathParam("key") @ApiParam(name="key", description="Key of the attribute to be removed.") String key);
	
	public abstract Session setAttribute(String sessionId, String key, String value);
	
	public abstract Session create(User user);
}
